package memory

import (
	"errors"
	"fmt"
	"sync"
	"time"

	"gitee.com/gomaster/book-library/entity"
)

// key ibsn
var bookBorrowMap= make(map[string]*entity.BorrowRecord)
var bookBackMap = make(map[string]*entity.BorrowRecord)

// map[userName][ibsn] = struct{}
var userLendMap = make(map[string]map[string]struct{})

// map[bookName][ibsn] = struct{}
var bookLendMap = make(map[string]map[string]struct{})

var borrowLock sync.Mutex

type MemBorrow struct {}

// BorrowAdd 图书借阅
func(m *MemBorrow)BorrowAdd(ibsn, username string) error {
	_, ok := bookBorrowMap[ibsn]; if ok {
		fmt.Printf("书籍已借出")
		return errors.New("book has borrow already")
	}

	bookInfo,ok := bookMap[ibsn]
	if !ok {
		fmt.Printf("当前图书不存在, ibsn:%s", ibsn)
		return errors.New("book does not exists, ibsn:"+ibsn)
	}
	bookBorrowMap[ibsn] = &entity.BorrowRecord{
		IBSN: ibsn,
		Name: username,
		BookName: bookInfo.Name,
	}

	if _, ok := userLendMap[username]; !ok {
		lendBook := make(map[string]struct{})
		lendBook[ibsn] = struct{}{}
		userLendMap[username] = lendBook
	} else {
		userLendMap[username][ibsn] = struct{}{}
	}

	if _, ok := bookLendMap[ibsn]; !ok {
		brBook := make(map[string]struct{})
		brBook[ibsn] = struct{}{}
		bookLendMap[bookInfo.Name] = brBook
	} else {
		bookLendMap[bookInfo.Name][ibsn] = struct{}{}
	}

	return nil
}

// BorrowBack 图书归还
func (m *MemBorrow) BorrowBack(ibsn, userName string) error {
	bbInfo,ok := bookBorrowMap[ibsn]
	if !ok {
		fmt.Printf("当前书籍没有借阅记录,ibsn:%s",ibsn)
		return nil
	}

	bkName := bbInfo.BookName
	bookLendMap := bookLendMap[bkName]

	bbInfo.BackTime = time.Now().Format(time.RFC3339)
	bbInfo.Status = entity.BookStatusInit

	borrowLock.Lock()
	// 删除借阅表中数据
	delete(bookBorrowMap,ibsn)
	// 删除图书借阅表中数据
	delete(bookLendMap,bkName)
	// 在归还图书表中，添加一条数据
	bookBackMap[ibsn] = bbInfo
	borrowLock.Unlock()
	return nil
}

// BorrowGet 查询图书借阅
func(m *MemBorrow)BorrowGet(ibsn string) *entity.BorrowRecord {
	// 在借阅表中查询数据
	record, ok := bookBorrowMap[ibsn]
	if ok {
		return record
	}

	// 在归还表中查询数据
	record, ok = bookBackMap[ibsn]
	if ok {
		return record
	}
	fmt.Printf("this ibsn have no borrow record")
	return nil
}

// BorrowListByName 根据用户名，查询借阅列表
func(m *MemBorrow)BorrowListByName(name string)[]*entity.BorrowRecord {
	lendBookMap, ok := userLendMap[name]
	if !ok {
		fmt.Printf("当前用户没有借阅记录")
		return nil
	}
	records := make([]*entity.BorrowRecord,0, len(lendBookMap))
	for ibsn := range lendBookMap {
		bookLendInfo, ok := bookBorrowMap[ibsn]
		if ok {
			records = append(records, bookLendInfo) 
			continue
		}
		bookBackInfo, ok := bookBackMap[ibsn]
		if ok {
			records = append(records, bookBackInfo) 
			continue
		}
		// 流程不会到达这里
		fmt.Printf("当前ibsn没有借阅记录, ibsn:%s", ibsn)
	}
	return records
}

// BorrowListByIbsn 根据 bookName，查询借阅, 当前只查询已经借阅出去的书籍记录
func(m *MemBorrow)BorrowListByBookName(bookName string)[]*entity.BorrowRecord{
	bookLendMap, ok := bookLendMap[bookName]; 
	if !ok {
		fmt.Printf("当前书籍没有借出记录, bookName:%s", bookName)
		return nil
	}

	records := make([]*entity.BorrowRecord, 0, len(bookLendMap))
	for bkName := range bookLendMap {
		records = append(records, bookBorrowMap[bkName])
	}
	return records
}